package com.zenithmind.common.context;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * 用户上下文工具类
 * 支持两种方式获取用户信息：
 * 1. 从Spring Security上下文获取（OAuth2/JWT）
 * 2. 从ThreadLocal获取（网关传递的用户信息）
 *
 * 支持多租户上下文管理
 */
@Slf4j
public class UserContext {

    private static final String USER_ID_CLAIM = "userId";
    private static final String USERNAME_CLAIM = "username";
    private static final String ROLES_CLAIM = "roles";
    private static final String TENANT_ID_CLAIM = "tenantId";
    private static final String TENANT_CODE_CLAIM = "tenantCode";

    // ThreadLocal存储用户信息（用于网关传递的用户信息）
    private static final ThreadLocal<String> USER_ID_HOLDER = new ThreadLocal<>();
    private static final ThreadLocal<String> USERNAME_HOLDER = new ThreadLocal<>();
    private static final ThreadLocal<String> USER_ROLES_HOLDER = new ThreadLocal<>();

    // ThreadLocal存储租户信息
    private static final ThreadLocal<String> TENANT_ID_HOLDER = new ThreadLocal<>();
    private static final ThreadLocal<String> TENANT_CODE_HOLDER = new ThreadLocal<>();

    /**
     * 设置用户ID（用于网关传递用户信息）
     */
    public static void setUserId(String userId) {
        USER_ID_HOLDER.set(userId);
    }

    /**
     * 设置用户名（用于网关传递用户信息）
     */
    public static void setUsername(String username) {
        USERNAME_HOLDER.set(username);
    }

    /**
     * 设置用户角色（用于网关传递用户信息）
     */
    public static void setUserRoles(String roles) {
        USER_ROLES_HOLDER.set(roles);
    }

    /**
     * 设置租户ID（用于网关传递租户信息）
     */
    public static void setTenantId(String tenantId) {
        TENANT_ID_HOLDER.set(tenantId);
    }

    /**
     * 设置租户编码（用于网关传递租户信息）
     */
    public static void setTenantCode(String tenantCode) {
        TENANT_CODE_HOLDER.set(tenantCode);
    }

    /**
     * 清理ThreadLocal（防止内存泄漏）
     */
    public static void clear() {
        USER_ID_HOLDER.remove();
        USERNAME_HOLDER.remove();
        USER_ROLES_HOLDER.remove();
        TENANT_ID_HOLDER.remove();
        TENANT_CODE_HOLDER.remove();
    }

    /**
     * 获取当前用户ID
     * 优先从ThreadLocal获取（网关传递），其次从Spring Security上下文获取
     * @return 用户ID，如果未登录返回null
     */
    public static String getUserId() {
        // 优先从ThreadLocal获取
        String userId = USER_ID_HOLDER.get();
        if (StringUtils.hasText(userId)) {
            return userId;
        }
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication == null || !authentication.isAuthenticated()) {
                log.warn("用户未认证，无法获取用户ID");
                return null;
            }

            // 从JWT token中获取用户ID
            if (authentication.getPrincipal() instanceof Jwt jwt) {
                String jwtUserId = jwt.getClaimAsString("user_id");
                if (StringUtils.hasText(jwtUserId)) {
                    return jwtUserId;
                }
                // 兼容旧版本的claim名称
                jwtUserId = jwt.getClaimAsString(USER_ID_CLAIM);
                if (StringUtils.hasText(jwtUserId)) {
                    return jwtUserId;
                }
            }
            
            // 从用户名中获取（备用方案）
            String username = authentication.getName();
            if (StringUtils.hasText(username) && !"anonymousUser".equals(username)) {
                return username;
            }
            
            log.warn("无法从认证信息中获取用户ID");
            return null;
        } catch (Exception e) {
            log.error("获取用户ID时发生异常", e);
            return null;
        }
    }
    
    /**
     * 获取当前用户名
     * 优先从ThreadLocal获取（网关传递），其次从Spring Security上下文获取
     * @return 用户名，如果未登录返回null
     */
    public static String getUsername() {
        // 优先从ThreadLocal获取
        String username = USERNAME_HOLDER.get();
        if (StringUtils.hasText(username)) {
            return username;
        }

        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication == null || !authentication.isAuthenticated()) {
                return null;
            }

            // 从JWT token中获取用户名
            if (authentication.getPrincipal() instanceof Jwt jwt) {
                String jwtUsername = jwt.getClaimAsString("preferred_username");
                if (StringUtils.hasText(jwtUsername)) {
                    return jwtUsername;
                }
                // 兼容旧版本的claim名称
                jwtUsername = jwt.getClaimAsString(USERNAME_CLAIM);
                if (StringUtils.hasText(jwtUsername)) {
                    return jwtUsername;
                }
            }

            return authentication.getName();
        } catch (Exception e) {
            log.error("获取用户名时发生异常", e);
            return null;
        }
    }

    /**
     * 获取当前租户ID
     * 优先从ThreadLocal获取（网关传递），其次从Spring Security上下文获取
     * @return 租户ID，如果未设置返回"default"
     */
    public static String getTenantId() {
        // 优先从ThreadLocal获取
        String tenantId = TENANT_ID_HOLDER.get();
        if (StringUtils.hasText(tenantId)) {
            return tenantId;
        }

        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication == null || !authentication.isAuthenticated()) {
                return "default"; // 返回默认租户
            }

            // 从JWT token中获取租户ID
            if (authentication.getPrincipal() instanceof Jwt jwt) {
                String jwtTenantId = jwt.getClaimAsString("tenant_id");
                if (StringUtils.hasText(jwtTenantId)) {
                    return jwtTenantId;
                }
                // 兼容旧版本的claim名称
                jwtTenantId = jwt.getClaimAsString(TENANT_ID_CLAIM);
                if (StringUtils.hasText(jwtTenantId)) {
                    return jwtTenantId;
                }
            }

            return "default"; // 默认租户
        } catch (Exception e) {
            log.error("获取租户ID时发生异常", e);
            return "default";
        }
    }

    /**
     * 获取当前租户编码
     * 优先从ThreadLocal获取（网关传递），其次从Spring Security上下文获取
     * @return 租户编码，如果未设置返回"default"
     */
    public static String getTenantCode() {
        // 优先从ThreadLocal获取
        String tenantCode = TENANT_CODE_HOLDER.get();
        if (StringUtils.hasText(tenantCode)) {
            return tenantCode;
        }

        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication == null || !authentication.isAuthenticated()) {
                return "default"; // 返回默认租户编码
            }

            // 从JWT token中获取租户编码
            if (authentication.getPrincipal() instanceof Jwt jwt) {
                String jwtTenantCode = jwt.getClaimAsString("tenant_code");
                if (StringUtils.hasText(jwtTenantCode)) {
                    return jwtTenantCode;
                }
                // 兼容旧版本的claim名称
                jwtTenantCode = jwt.getClaimAsString(TENANT_CODE_CLAIM);
                if (StringUtils.hasText(jwtTenantCode)) {
                    return jwtTenantCode;
                }
            }

            return "default"; // 默认租户编码
        } catch (Exception e) {
            log.error("获取租户编码时发生异常", e);
            return "default";
        }
    }
    
    /**
     * 获取当前用户角色
     * 优先从ThreadLocal获取（网关传递），其次从Spring Security上下文获取
     * @return 用户角色列表
     */
    @SuppressWarnings("unchecked")
    public static java.util.List<String> getUserRoles() {
        // 优先从ThreadLocal获取
        String roles = USER_ROLES_HOLDER.get();
        if (StringUtils.hasText(roles)) {
            // 解析角色字符串（逗号分隔）
            return java.util.Arrays.asList(roles.split(","));
        }

        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication == null || !authentication.isAuthenticated()) {
                return java.util.Collections.emptyList();
            }

            // 从JWT token中获取角色
            if (authentication.getPrincipal() instanceof Jwt jwt) {
                Object jwtRoles = jwt.getClaim(ROLES_CLAIM);
                if (jwtRoles instanceof java.util.List) {
                    log.debug("从JWT获取到的角色信息: {}", jwtRoles);
                    return (java.util.List<String>) jwtRoles;
                }
                // 如果是字符串，尝试解析为列表
                if (jwtRoles instanceof String) {
                    log.debug("从JWT获取到的角色信息是字符串: {}", jwtRoles);
                    String rolesStr = (String) jwtRoles;
                    if (rolesStr.contains(",")) {
                        return java.util.Arrays.asList(rolesStr.split(","));
                    } else {
                        return java.util.Collections.singletonList(rolesStr);
                    }
                }
            }

            // 从权限中获取角色
            return authentication.getAuthorities().stream()
                    .map(authority -> authority.getAuthority())
                    .filter(authority -> authority.startsWith("ROLE_"))
                    .map(authority -> authority.substring(5)) // 移除 "ROLE_" 前缀
                    .collect(java.util.stream.Collectors.toList());
        } catch (Exception e) {
            log.error("获取用户角色时发生异常", e);
            return java.util.Collections.emptyList();
        }
    }
    
    /**
     * 检查当前用户是否有指定角色
     * @param role 角色名称
     * @return 是否有该角色
     */
    public static boolean hasRole(String role) {
        return getUserRoles().contains(role);
    }
    
    /**
     * 检查当前用户是否为管理员
     * @return 是否为管理员
     */
    public static boolean isAdmin() {
        log.debug("检查管理员权限，当前用户ID: {}", getUserId());
        log.debug("检查管理员权限，当前用户名: {}", getUsername());
        List<String> roles = getUserRoles();
        log.debug("检查管理员权限，当前用户角色: {}", roles);
        
        // 尝试从Spring Security上下文直接获取认证信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            log.debug("当前认证信息: {}, 类型: {}", authentication, authentication.getClass().getName());
            log.debug("当前认证权限: {}", authentication.getAuthorities());
        }
        
        // 宽松检查，支持多种可能的角色格式
        boolean isAdmin = roles.stream().anyMatch(role -> 
               "ADMIN".equalsIgnoreCase(role) || 
               "SUPER_ADMIN".equalsIgnoreCase(role) || 
               "ROLE_ADMIN".equalsIgnoreCase(role) || 
               "ROLE_SUPER_ADMIN".equalsIgnoreCase(role));
        
        log.debug("用户是否具有管理员权限: {}", isAdmin);
        return isAdmin;
    }
    
    /**
     * 获取当前用户ID，如果未登录则抛出异常
     * @return 用户ID
     * @throws IllegalStateException 如果用户未登录
     */
    public static String requireUserId() {
        String userId = getUserId();
        if (userId == null) {
            throw new IllegalStateException("用户未登录或无法获取用户ID");
        }
        return userId;
    }
    
    /**
     * 检查当前用户是否已登录
     * @return 是否已登录
     */
    public static boolean isAuthenticated() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication != null && 
               authentication.isAuthenticated() && 
               !"anonymousUser".equals(authentication.getName());
    }
}
